﻿using System;
using System.Text;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using UCL.Powersource.Mock;

namespace Powersource_UnitTests.StatisticsTest
{
    /// <summary>
    /// Summary description for BaseStatisticTest
    /// </summary>
    [TestClass]
    public class StatisticTeamBaseTest
    {
        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        #endregion

        private DummyStatistic1 stat;
        private DummyTeamProjectCollectionConfiguration teamProjCollConfig;
        // Use TestInitialize to run code before running each test 
        [TestInitialize()]
        public void MyTestInitialize() 
        {
            stat = new DummyStatistic1();
            teamProjCollConfig = new DummyTeamProjectCollectionConfiguration();
        }
        
        // Use TestCleanup to run code after each test has run
        [TestCleanup()]
        public void MyTestCleanup()
        {
            stat = null;
            teamProjCollConfig = null;        
        }
        

        [TestMethod]
        public void TeamStatTestResolveOneProjectOneTimeframe()
        {
            var proj1 = teamProjCollConfig.TeamProjectConfigurations[0];
            var proj5 = teamProjCollConfig.TeamProjectConfigurations[4];
            var timeframe = teamProjCollConfig._ProjectCollectionTimeFrames[0];
            var timeframe2 = teamProjCollConfig._ProjectCollectionTimeFrames[1];
            stat.Resolve(proj1, timeframe);
            Assert.IsTrue(stat.TeamResults.ContainsKey(proj1), "No entry for {0} in TeamResults", proj1.UniqueName);
            Assert.IsTrue(stat.TeamResults[proj1].ContainsKey(timeframe), "No entry for {0}:{1} in TeamResults", proj1.UniqueName, timeframe.Label);
            Assert.IsFalse(stat.TeamResults[proj1].ContainsKey(timeframe2), "Entry created for {0}:{1} when not requested", proj1.UniqueName, timeframe2.Label);
            Assert.IsNotNull(stat.TeamResults[proj1][timeframe].Value, "Null value for {0}:{1} in TeamResults", proj1.UniqueName, timeframe.Label);

            stat.Resolve(proj5, timeframe);
            Assert.IsFalse(stat.TeamResults.ContainsKey(proj5), "Entry created for {0} even though it was not set for statistics", proj5.UniqueName);
        }

        [TestMethod]
        public void TeamStatTestResolveOneProjectOneTimeframeForceRecalculate()
        {
            var proj1 = teamProjCollConfig.TeamProjectConfigurations[0];
            var timeframe = teamProjCollConfig._ProjectCollectionTimeFrames[0];
            stat.Resolve(proj1, timeframe);

            var result1 = stat.TeamResults[proj1][timeframe];

            stat.Resolve(proj1, timeframe, true);

            var result2 = stat.TeamResults[proj1][timeframe];

            Assert.AreNotEqual(result1, result2, "Same results even though we forced recalculation");
        }

        [TestMethod]
        public void TeamStatTestResolveOneProjectAllTimeframes()
        {
            var proj1 = teamProjCollConfig.TeamProjectConfigurations[0];
            var proj2 = teamProjCollConfig.TeamProjectConfigurations[1];
            stat.Resolve(proj1);

            Assert.IsTrue(stat.TeamResults.ContainsKey(proj1), "No entry for {0} in TeamResults", proj1.UniqueName);
            Assert.IsFalse(stat.TeamResults.ContainsKey(proj2), "Entry created for {0} even though not requested", proj2.UniqueName);
            foreach (var timeframe in proj1.ProjectTimeframes)
            {
                Assert.IsTrue(stat.TeamResults[proj1].ContainsKey(timeframe), "No entry for {0}:{1} in TeamResults", proj1.UniqueName, timeframe.Label);
                Assert.IsNotNull(stat.TeamResults[proj1][timeframe].Value, "Null value for {0}:{1} in TeamResults", proj1.UniqueName, timeframe.Label);
            }
        }

        [TestMethod]
        public void TeamStatTestResolveOneProjectCollectionOneTimeframe()
        {
            var timeframe = teamProjCollConfig._ProjectCollectionTimeFrames[0];
            var timeframe2 = teamProjCollConfig._ProjectCollectionTimeFrames[1];

            stat.Resolve(teamProjCollConfig, timeframe);
            foreach (var proj in teamProjCollConfig)
            {
                if (proj != teamProjCollConfig.TeamProjectConfigurations[4])
                {
                    Assert.IsTrue(stat.TeamResults.ContainsKey(proj), "No entry for {0} in TeamResults", proj.UniqueName);
                    Assert.IsTrue(stat.TeamResults[proj].ContainsKey(timeframe), "No entry for {0}:{1} in TeamResults", proj.UniqueName, timeframe.Label);
                    Assert.IsFalse(stat.TeamResults[proj].ContainsKey(timeframe2), "Entry created for {0}:{1} when not requested", proj.UniqueName, timeframe2.Label);
                    Assert.IsNotNull(stat.TeamResults[proj][timeframe].Value, "Null value for {0}:{1} in TeamResults", proj.UniqueName, timeframe.Label);
                }
                else
                    Assert.IsFalse(stat.TeamResults.ContainsKey(teamProjCollConfig.TeamProjectConfigurations[4]), "Entry created for {0} even though it was not set for statistics", teamProjCollConfig.TeamProjectConfigurations[4].UniqueName);
            }
        }

        [TestMethod]
        public void TeamStatTestResolveOneProjectCollectionAllTimeframes()
        {
            stat.Resolve(teamProjCollConfig);

            foreach (var proj in teamProjCollConfig)
            {
                if (proj != teamProjCollConfig.TeamProjectConfigurations[4])
                {
                    Assert.IsTrue(stat.TeamResults.ContainsKey(proj), "No entry for {0} in TeamResults", proj.UniqueName);

                    foreach (var timeframe in teamProjCollConfig.ProjectCollectionTimeFrames)
                    {
                        Assert.IsTrue(stat.TeamResults[proj].ContainsKey(timeframe), "No entry for {0}:{1} in TeamResults", proj.UniqueName, timeframe.Label);
                        Assert.IsNotNull(stat.TeamResults[proj][timeframe].Value, "Null value for {0}:{1} in TeamResults", proj.UniqueName, timeframe.Label);
                    }
                }
                else
                    Assert.IsFalse(stat.TeamResults.ContainsKey(teamProjCollConfig.TeamProjectConfigurations[4]), "Entry created for {0} even though it was not set for statistics", teamProjCollConfig.TeamProjectConfigurations[4].UniqueName);
            }
        }

        [TestMethod]
        public void TeamStatTestClearInvalidEntries()
        {
            stat.Resolve(teamProjCollConfig);
            var proj1 = teamProjCollConfig.TeamProjectConfigurations[0];
            var timeframe = teamProjCollConfig._ProjectCollectionTimeFrames[0];
            teamProjCollConfig.TeamProjectConfigurations.Remove(proj1);
            teamProjCollConfig._ProjectCollectionTimeFrames.Remove(timeframe);

            stat.ClearInvalidEntries(teamProjCollConfig);

            Assert.IsFalse(stat.TeamResults.ContainsKey(proj1), "Results still contain entry for {0}", proj1.UniqueName);
            foreach (var entry in stat.TeamResults)
            {
                Assert.IsFalse(entry.Value.ContainsKey(timeframe), "Results still contain entry for {0}:{1}", entry.Key.UniqueName, timeframe.Label);
            }
        }
    }
}
